library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity invmixcol is
    Port ( clk : in  STD_LOGIC;
			  datain : in  STD_LOGIC_VECTOR (31 downto 0);
           dataout : out  STD_LOGIC_VECTOR (31 downto 0));
end invmixcol;

architecture Structural of invmixcol is
	alias s3c : std_logic_vector(7 downto 0) is datain(7 downto 0);
	alias s2c : std_logic_vector(7 downto 0) is datain(15 downto 8);
	alias s1c : std_logic_vector(7 downto 0) is datain(23 downto 16);
	alias s0c : std_logic_vector(7 downto 0) is datain(31 downto 24);
	
	alias o_s3c : std_logic_vector(7 downto 0) is dataout(7 downto 0);
	alias o_s2c : std_logic_vector(7 downto 0) is dataout(15 downto 8);
	alias o_s1c : std_logic_vector(7 downto 0) is dataout(23 downto 16);
	alias o_s0c : std_logic_vector(7 downto 0) is dataout(31 downto 24);
	
	signal s0c_x9, s0c_xb, s0c_xd, s0c_xe,
			 s1c_x9, s1c_xb, s1c_xd, s1c_xe,
			 s2c_x9, s2c_xb, s2c_xd, s2c_xe,
			 s3c_x9, s3c_xb, s3c_xd, s3c_xe : std_logic_vector(7 downto 0);
begin
	-- Obliczanie s0, s1c, s2c i s3c przemnozonych przez 09, 0b, 0d, 0e
	mul2_s0c_x9: entity work.mul4(Behavioral)
		port map (datain => s0c,	multiplier => X"9", dataout => s0c_x9);
	mul2_s0c_xb: entity work.mul4(Behavioral)
		port map (datain => s0c,	multiplier => X"B", dataout => s0c_xb);
	mul2_s0c_xd: entity work.mul4(Behavioral)
		port map (datain => s0c,	multiplier => X"D", dataout => s0c_xd);
	mul2_s0c_xe: entity work.mul4(Behavioral)
		port map (datain => s0c,	multiplier => X"E", dataout => s0c_xe);
	mul2_s1c_x9: entity work.mul4(Behavioral)
		port map (datain => s1c,	multiplier => X"9", dataout => s1c_x9);
	mul2_s1c_xb: entity work.mul4(Behavioral)
		port map (datain => s1c,	multiplier => X"B", dataout => s1c_xb);
	mul2_s1c_xd: entity work.mul4(Behavioral)
		port map (datain => s1c,	multiplier => X"D", dataout => s1c_xd);
	mul2_s1c_xe: entity work.mul4(Behavioral)
		port map (datain => s1c,	multiplier => X"E", dataout => s1c_xe);
	mul2_s2c_x9: entity work.mul4(Behavioral)
		port map (datain => s2c,	multiplier => X"9", dataout => s2c_x9);
	mul2_s2c_xb: entity work.mul4(Behavioral)
		port map (datain => s2c,	multiplier => X"B", dataout => s2c_xb);
	mul2_s2c_xd: entity work.mul4(Behavioral)
		port map (datain => s2c,	multiplier => X"D", dataout => s2c_xd);
	mul2_s2c_xe: entity work.mul4(Behavioral)
		port map (datain => s2c,	multiplier => X"E", dataout => s2c_xe);
	mul2_s3c_x9: entity work.mul4(Behavioral)
		port map (datain => s3c,	multiplier => X"9", dataout => s3c_x9);
	mul2_s3c_xb: entity work.mul4(Behavioral)
		port map (datain => s3c,	multiplier => X"B", dataout => s3c_xb);
	mul2_s3c_xd: entity work.mul4(Behavioral)
		port map (datain => s3c,	multiplier => X"D", dataout => s3c_xd);
	mul2_s3c_xe: entity work.mul4(Behavioral)
		port map (datain => s3c,	multiplier => X"E", dataout => s3c_xe);

	process (clk)
	begin
		if (rising_edge(clk)) then
			-- Obliczanie wedlug wzoru 5.10 z FIPS-197 (s. 23)
			o_s0c <= s0c_xe xor s1c_xb xor s2c_xd xor s3c_x9;
			o_s1c <= s0c_x9 xor s1c_xe xor s2c_xb xor s3c_xd;
			o_s2c <= s0c_xd xor s1c_x9 xor s2c_xe xor s3c_xb;
			o_s3c <= s0c_xb xor s1c_xd xor s2c_x9 xor s3c_xe;
		end if;
	end process;
end Structural;
